package com.xin.di.uav.operate.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xin.di.uav.operate.rest.UserExtraRest;
import com.xin.di.uav.user.mapper.UserExtraMapper;
import com.xin.di.uav.user.mapper.UserMapper;
import com.xin.di.uav.operate.service.IUserService;
import com.xin.di.uav.common.awt.JwtUtil;
import com.xin.di.uav.common.enums.UserStatusEnum;
import com.xin.di.uav.common.request.common.IdRequest;
import com.xin.di.uav.common.request.user.UserExtraRequest;
import com.xin.di.uav.common.response.user.UserDetailResponse;
import com.xin.di.uav.common.response.user.UserResponse;
import com.xin.di.uav.common.utils.BeanUtil;
import com.xin.di.uav.common.utils.PhoneDesensitizationUtil;
import com.xin.di.uav.common.utils.PhoneEncoderUtil;
import com.xin.di.uav.user.entity.User;
import com.xin.di.uav.user.entity.UserExtra;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author LTQ
 * @since 2023-04-03
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserExtraRest userExtraRest;

    @Autowired
    private UserExtraMapper userExtraMapper;

    @Autowired
    private IUserService iUserService;

    @Autowired
    private PhoneEncoderUtil phoneEncoderUtil;

    private final static Integer PHONE_CHECK = 11;

    @Override
    public UserResponse getByUserId() {
        String userId = JwtUtil.getUserId();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", userId);
        User user = iUserService.selectOne(userQueryWrapper, true);
        UserResponse userResponse = BeanUtil.copyProperties(user, UserResponse.class);
        return userResponse;
    }

    @Override
    public UserResponse getByUserId(String userId) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", userId);
        User user = iUserService.selectOne(userQueryWrapper, false);
        UserResponse userResponse = BeanUtil.copyProperties(user, UserResponse.class);
        return userResponse;
    }

    @Override
    public User getUser() {
        String userId = JwtUtil.getUserId();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", userId);
        User user = iUserService.selectOne(userQueryWrapper, false);
        return user;
    }

    @Override
    public Long getTotal(@RequestParam(required = false) String phoneNumber, @RequestParam(required = false) Integer platformCode) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(phoneNumber)) {
            phoneNumber = phoneEncoderUtil.encryptString(phoneNumber);
            userQueryWrapper.eq("phone_number", phoneNumber);
        }

        if (!ObjectUtils.isEmpty(platformCode)) {
            userQueryWrapper.eq("platform_code", platformCode);
        }
        Long cnt = userMapper.selectCount(userQueryWrapper);
        return cnt;
    }

    @Override
    public List<UserDetailResponse> getUsers(Integer page, Integer size, String phoneNumber, Integer platformCode) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(phoneNumber)) {
            phoneNumber = phoneEncoderUtil.encryptString(phoneNumber);
            userQueryWrapper.eq("phone_number", phoneNumber);
        }
        if (!ObjectUtils.isEmpty(platformCode)) {
            userQueryWrapper.eq("platform_code", platformCode);
        }
        userQueryWrapper.orderByDesc("create_time");
        Page<User> userPage = new Page<>(page, size);
        IPage<User> userIPage = iUserService.selectPage(userPage, userQueryWrapper, true);
        List<UserDetailResponse> userDetailResponseList = BeanUtil.copyProperties(userIPage.getRecords(), UserDetailResponse.class);
        List<String> userIds = userDetailResponseList.stream().map(userDetailResponse -> userDetailResponse.getId()).collect(Collectors.toList());
        QueryWrapper<UserExtra> userExtraQueryWrapper = new QueryWrapper<>();
        if (!CollectionUtils.isEmpty(userIds)) {
            userExtraQueryWrapper.in("user_id", userIds);
            List<UserExtra> extras = userExtraMapper.selectList(userExtraQueryWrapper);
            userDetailResponseList.forEach(userDetailResponse -> {
                userDetailResponse.setPhoneNumber(DesensitizedUtil.desensitized(userDetailResponse.getPhoneNumber(), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
                extras.forEach(extra -> {
                    if (userDetailResponse.getId().equals(extra.getUserId())) {
                        userDetailResponse.setLastLoginTime(extra.getLastLoginTime());
                    }
                });
            });
        }
        return userDetailResponseList;
    }

    @Override
    public void freeze(IdRequest idRequest) {
        User user = userMapper.selectById(idRequest.getId());
        if (ObjectUtils.isEmpty(user)) {
            throw new RuntimeException("用户不存在");
        }
        user.setStatus(UserStatusEnum.BLOCK.getValue());
        userMapper.updateById(user);
    }

    @Override
    public void restore(IdRequest idRequest) {
        User user = userMapper.selectById(idRequest.getId());
        if (ObjectUtils.isEmpty(user)) {
            throw new RuntimeException("用户不存在");
        }
        user.setStatus(UserStatusEnum.NORMAL.getValue());
        userMapper.updateById(user);
    }

    @Override
    public int insert(User entity) {
        //加密
        String phoneNumber = entity.getPhone();
        if (!ObjectUtils.isEmpty(phoneNumber)) {
            String encryptPhone = phoneEncoderUtil.encryptString(phoneNumber);
            entity.setPhone(encryptPhone);
        }
        return userMapper.insert(entity);
    }


    @Override
    public User selectOne(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper, Boolean isCover) {
        User user = userMapper.selectOne(queryWrapper);
        if (!ObjectUtils.isEmpty(user)) {
            String phoneNumber = user.getPhone();
            if (isCover) {
                phoneNumber = PhoneDesensitizationUtil.phoneDesensitization(phoneNumber);
                user.setPhone(phoneNumber);
            }

        }
        return user;
    }

    @Override
    public List<User> selectList(Wrapper<User> queryWrapper, Boolean isCover) {
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(user -> {
            String phoneNumber = user.getPhone();
            phoneNumber = phoneEncoderUtil.decryptString(phoneNumber);
            if (isCover) {
                phoneNumber = phoneNumber.substring(0, 3) + "****" + phoneNumber.substring(7);
            }
            user.setPhone(phoneNumber);
        });
        return users;
    }

    @Override
    public String saveUserWithCover(User user) {
        //加密
        String phoneNumber = user.getPhone();
        if (!ObjectUtils.isEmpty(phoneNumber)) {
            String encryptPhone = phoneEncoderUtil.encryptString(phoneNumber);
            user.setPhone(encryptPhone);
        }
        return userMapper.saveUser(user);
    }

    @Override
    public IPage<User> selectPage(Page<User> userPage, QueryWrapper<User> userQueryWrapper, Boolean isCover) {
        IPage<User> userIPage = userMapper.selectPage(userPage, userQueryWrapper);
        List<User> users = userIPage.getRecords();
        for (User user : users) {
            String phoneNumber = user.getPhone();
            if (StringUtils.isAllBlank(phoneNumber) || phoneNumber.length() != PHONE_CHECK) {
                isCover = false;
            }
            phoneNumber = phoneEncoderUtil.decryptString(phoneNumber);
            if (isCover) {
                phoneNumber = phoneNumber.substring(0, 3) + "****" + phoneNumber.substring(7);
            }
            user.setPhone(phoneNumber);
        }
        return userIPage;
    }

    @Override
    public User getNormalUser(String userId) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", userId);
        userQueryWrapper.eq("status", UserStatusEnum.NORMAL.getValue());
        return userMapper.selectOne(userQueryWrapper);
    }

    @Override
    public User getOne(String phoneNumber, String countryCode, Integer platformCode) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().eq(User::getPhone, phoneNumber)
                .eq(User::getCountryCode, countryCode)
                .eq(User::getPlatformCode, platformCode);
        return userMapper.selectOne(userQueryWrapper);
    }

    @Override
    public void dealLogin(Date date, String userId) {
        UserExtra userExtra = userExtraRest.getByUserId(userId);
        if (ObjectUtils.isEmpty(userExtra)) {
            UserExtraRequest userExtraRequest = new UserExtraRequest();
            userExtraRequest.setUserId(userId);
            userExtraRequest.setLastLoginTime(date);
            userExtraRest.add(userExtraRequest);
        } else {
            UserExtraRequest userExtraRequest = BeanUtil.copyProperties(userExtra, UserExtraRequest.class);
            userExtraRequest.setLastLoginTime(date);
            userExtraRest.edit(userExtraRequest);
        }
    }

    @Override
    public List<User> queryUserListByPhoneSet(Set<String> phoneSet) {
        return userMapper.selectList(new QueryWrapper<User>().in("phone_number", phoneSet));
    }

    @Override
    public List<User> getList(String phoneNumber, String countryCode, List<Integer> platformCodes) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("phone_number", phoneNumber);
        userQueryWrapper.eq("country_code", countryCode);
        userQueryWrapper.in("platform_code", platformCodes);
        List<User> users = userMapper.selectList(userQueryWrapper);
        return users;
    }
}
